﻿using System.Security.Cryptography;
using System.Text;
namespace CsharpPro._1106;

public class UserServiceImpl : IUserService
{
    private Dictionary<string, User> _users = new Dictionary<string, User>();

    public void RunSystem()
    {
        bool isRunning = true;
        while (isRunning)
        {
            Console.WriteLine("\n=== 主菜单 ===");
            Console.WriteLine("1. 登录");
            Console.WriteLine("2. 注册");
            Console.WriteLine("3. 退出");
            Console.WriteLine("4. 查看所有用户");
            Console.WriteLine("5. 删除用户");
            Console.Write("请选择功能（1-5）：");

            // 处理输入null风险：若输入为null则转为空字符串
            string choice = (Console.ReadLine() ?? "").Trim();
            switch (choice)
            {
                case "1":
                    Login();
                    break;
                case "2":
                    Register();
                    break;
                case "3":
                    isRunning = false;
                    Console.WriteLine("感谢使用，再见！");
                    break;
                case "4":
                    ListAllUsers();
                    Console.WriteLine("调用成功");
                    break;
                case "5":
                    DeleteUser();
                    break;
                default:
                    Console.WriteLine("请输入有效数字！");
                    break;
            }
        }
    }

    public void Register()
    {
        Console.WriteLine("\n=== 用户注册 ===");

        // 用户名输入及校验（处理null风险）
        string username;
        while (true)
        {
            Console.Write("请输入用户名（3-15个字符，仅含字母、数字、下划线）：");
            username = (Console.ReadLine() ?? "").Trim(); // 处理null

            if (string.IsNullOrWhiteSpace(username))
            {
                Console.WriteLine("用户名不可为空！");
                continue;
            }

            if (username.Length < 3 || username.Length > 15)
            {
                Console.WriteLine("用户名长度必须为3-15个字符！");
                continue;
            }

            if (!System.Text.RegularExpressions.Regex.IsMatch(username, @"^[a-zA-Z0-9_]+$"))
            {
                Console.WriteLine("用户名只能包含字母、数字和下划线！");
                continue;
            }

            if (_users.ContainsKey(username))
            {
                Console.WriteLine("用户名已存在，请更换！");
                continue;
            }

            break;
        }

        // 密码输入及校验（优化确认密码体验：仅重复确认密码）
        string password;
        while (true)
        {
            Console.Write("请输入密码（6-20个字符，需包含至少1个大写字母、1个小写字母和1个数字）：");
            password = Console.ReadLine() ?? ""; // 处理null（密码允许有空格？此处按原逻辑不Trim，保留输入）

            if (string.IsNullOrWhiteSpace(password))
            {
                Console.WriteLine("密码不可为空！");
                continue;
            }

            if (password.Length < 6 || password.Length > 20)
            {
                Console.WriteLine("密码长度必须为6-20个字符！");
                continue;
            }

            if (!System.Text.RegularExpressions.Regex.IsMatch(password, @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"))
            {
                Console.WriteLine("密码必须包含至少1个大写字母、1个小写字母和1个数字！");
                continue;
            }

            // 仅重复输入确认密码，无需重新输入原密码
            while (true)
            {
                Console.Write("请确认密码：");
                string confirmPassword = Console.ReadLine() ?? "";
                if (password == confirmPassword)
                {
                    break; // 确认成功，跳出确认循环
                }

                Console.WriteLine("两次密码不一致，请重新确认！");
            }

            break; // 密码校验全部通过
        }

        // 生成盐值并加密密码（解决明文存储问题）
        string salt = GenerateSalt();
        string hashedPassword = HashPassword(password, salt);

        // 将用户添加到字典（确保注册后存入_users）
        _users.Add(username, new User(username, hashedPassword, salt));
        Console.WriteLine("注册成功！请返回主菜单选择登录。");
    }

    public void Login()
    {
        Console.WriteLine("\n=== 用户登录 ===");

        // 用户名输入（处理null风险）
        Console.Write("请输入用户名：");
        string username = (Console.ReadLine() ?? "").Trim();
        if (string.IsNullOrWhiteSpace(username))
        {
            Console.WriteLine("用户名不可为空！");
            return;
        }

        // 密码输入（处理null风险）
        Console.Write("请输入密码：");
        string password = Console.ReadLine() ?? "";
        if (string.IsNullOrWhiteSpace(password))
        {
            Console.WriteLine("密码不可为空！");
            return;
        }

        // 校验_users字典中的用户信息
        if (_users.TryGetValue(username, out User user))
        {
            // 用存储的盐值加密输入密码，与存储的哈希密码比较
            string inputHashedPassword = HashPassword(password, user.Salt);
            if (inputHashedPassword == user.HashedPassword)
            {
                Console.WriteLine("登录成功！欢迎进入系统首页（模拟）。");
            }
            else
            {
                Console.WriteLine("密码错误！");
            }
        }
        else
        {
            Console.WriteLine("用户名不存在！");
        }
    }
    public void ListAllUsers()
    {
        Console.WriteLine("\n=== 所有注册用户 ===");
        if (_users.Count == 0)
        {
            Console.WriteLine("暂无注册用户！");
            return;
        }

        foreach (var user in _users.Values)
        {
            Console.WriteLine($"用户名：{user.Username}");
        }
        Console.WriteLine($"当前用户数量：{_users.Count}");
    }


// 简化删除逻辑（直接调用Remove）
    public void DeleteUser()
    {
        Console.WriteLine("\n=== 删除用户 ===");
        if (_users.Count == 0)
        {
            Console.WriteLine("暂无注册用户，无法删除！");
            return;
        }

        // 处理输入null风险
        Console.Write("请输入要删除的用户名：");
        string username = (Console.ReadLine() ?? "").Trim();
        if (string.IsNullOrWhiteSpace(username))
        {
            Console.WriteLine("用户名不可为空！");
            return;
        }

        // 直接删除并判断结果
        if (_users.Remove(username))
        {
            Console.WriteLine($"用户「{username}」已成功删除！");
        }
        else
        {
            Console.WriteLine("用户名不存在，无法删除！");
        }
    }

    // 生成随机盐值（用于密码加密）
    private string GenerateSalt()
    {
        byte[] saltBytes = new byte[16];
        using (var rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(saltBytes);
        }
        return Convert.ToBase64String(saltBytes);
    }

    // 密码加密（密码+盐值哈希）
    private string HashPassword(string password, string salt)
    {
        byte[] saltBytes = Convert.FromBase64String(salt);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

        // 使用PBKDF2算法（更安全的哈希方式）
        using (var pbkdf2 = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 10000, HashAlgorithmName.SHA256))
        {
            byte[] hashBytes = pbkdf2.GetBytes(32); // 32字节哈希结果
            return Convert.ToBase64String(hashBytes);
        }
    }
}